using System;
using System.Collections;
using System.Collections.Generic;

namespace EntityKit.Runtime
{
    /// <summary>
    /// 可观察的HashSet类，当集合内容发生变化时会触发相应的事件
    /// </summary>
    /// <typeparam name="T">集合元素的类型</typeparam>
    public class BindableHashSet<T> : IEnumerable<T>, IEnumerable
    {
        private HashSet<T> mSet = new HashSet<T>();
        
        /// <summary>
        /// 当向集合中添加元素时触发的事件
        /// </summary>
        public event Action<T> OnItemAdded;
        
        /// <summary>
        /// 当从集合中移除元素时触发的事件
        /// </summary>
        public event Action<T> OnItemRemoved;
        
        /// <summary>
        /// 当集合被清空时触发的事件
        /// </summary>
        public event Action OnCleared;
        
        /// <summary>
        /// 当集合内容发生任何变化时触发的事件
        /// </summary>
        public event Action OnChanged;
        
        /// <summary>
        /// 获取集合中元素的数量
        /// </summary>
        public int Count => mSet.Count;
        
        /// <summary>
        /// 向集合中添加元素
        /// </summary>
        /// <param name="item">要添加的元素</param>
        /// <returns>如果元素已添加到集合中，则为true；如果元素已在集合中，则为false</returns>
        public bool Add(T item)
        {
            bool added = mSet.Add(item);
            if (added)
            {
                OnItemAdded?.Invoke(item);
                OnChanged?.Invoke();
            }
            return added;
        }
        
        /// <summary>
        /// 从集合中移除特定元素
        /// </summary>
        /// <param name="item">要移除的元素</param>
        /// <returns>如果成功移除了元素，则为true；否则为false</returns>
        public bool Remove(T item)
        {
            bool removed = mSet.Remove(item);
            if (removed)
            {
                OnItemRemoved?.Invoke(item);
                OnChanged?.Invoke();
            }
            return removed;
        }
        
        /// <summary>
        /// 清空集合中的所有元素
        /// </summary>
        public void Clear()
        {
            mSet.Clear();
            OnCleared?.Invoke();
            OnChanged?.Invoke();
        }
        
        /// <summary>
        /// 确定集合是否包含特定元素
        /// </summary>
        /// <param name="item">要在集合中定位的元素</param>
        /// <returns>如果在集合中找到item，则为true；否则为false</returns>
        public bool Contains(T item)
        {
            return mSet.Contains(item);
        }
        
        /// <summary>
        /// 获取一个枚举器，用于遍历集合
        /// </summary>
        /// <returns>可用于遍历集合的枚举器</returns>
        public IEnumerator<T> GetEnumerator()
        {
            return mSet.GetEnumerator();
        }
        
        /// <summary>
        /// 获取一个枚举器，用于遍历集合
        /// </summary>
        /// <returns>可用于遍历集合的枚举器</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        
        /// <summary>
        /// 返回集合中所有元素的字符串表示形式
        /// </summary>
        /// <returns>集合的字符串表示形式</returns>
        public override string ToString()
        {
            return $"BindableHashSet<{typeof(T).Name}> (Count: {Count})";
        }
    }
}